#include once <realloc.asm>
; String library

__STRASSIGN: ; Performs a$ = b$ (HL = address of a$; DE = Address of b$)
                     ;- PROC
                     ;- LOCAL __STRREALLOC
                     ;- LOCAL __STRCONTINUE
                     ;- LOCAL __B_IS_NULL
                     ;- LOCAL __NOTHING_TO_COPY
lda z80_d            ;- ld b,d
sta z80_b
lda z80_e            ;- ld c,e
sta z80_c
lda z80_b            ;- ld a,b
sta z80_a
ora z80_c            ;- or c
                     ;- jr z, __B_IS_NULL
lda z80_e            ;- ex de,hl
ldx z80_l
stx z80_e
sta z80_l
lda z80_d
ldx z80_h
stx z80_d
sta z80_h
                     ;- ld c,(hl)
inc z80_l            ;- inc hl
bne *+4
inc z80_h
                     ;- ld b,(hl)
                     ;- dec hl		; BC = LEN(b$)
lda z80_e            ;- ex de,hl	; DE = &b$
ldx z80_l
stx z80_e
sta z80_l
lda z80_d
ldx z80_h
stx z80_d
sta z80_h

__B_IS_NULL:		; Jumps here if B$ pointer is NULL
                     ;- inc bc
                     ;- inc bc		; BC = BC + 2  ; (LEN(b$) + 2 bytes for storing length)
lda z80_e            ;- push de
pha
lda z80_d
pha
lda z80_l            ;- push hl
pha
lda z80_h
pha
lda z80_h            ;- ld a,h
sta z80_a
ora z80_l            ;- or l
                     ;- jr z, __STRREALLOC
                     ;- dec hl
ldy #$00             ;- ld d,(hl)
lda (z80_hl),y
sta z80_d
                     ;- dec hl
ldy #$00             ;- ld e, (hl)	; DE = MEMBLOCKSIZE(a$)
lda (z80_hl),y
sta z80_e
                     ;- dec de
                     ;- dec de		; DE = DE - 2  ; (Membloksize takes 2 bytes for memblock length)
lda z80_b            ;- ld h,b
sta z80_h
lda z80_c            ;- ld l, c		; HL = LEN(b$) + 2  => Minimum block size required
sta z80_l
lda z80_e            ;- ex de, hl	; Now HL = BLOCKSIZE(a$), DE = LEN(b$) + 2
ldx z80_l
stx z80_e
sta z80_l
lda z80_d
ldx z80_h
stx z80_d
sta z80_h
ora z80_a            ;- or a		; Prepare to subtract BLOCKSIZE(a$) - LEN(b$)
                     ;- sbc hl, de  ; Carry if len(b$) > Blocklen(a$)
jcc __STRREALLOC     ;- jr c, __STRREALLOC ; No need to realloc
; Need to reallocate at least to len(b$) + 2
lda z80_e            ;- ex de,hl	; DE = Remaining bytes in a$ mem block.
ldx z80_l
stx z80_e
sta z80_l
lda z80_d
ldx z80_h
stx z80_d
sta z80_h
lda #4               ;- ld hl, 4
sta z80_l
lda #0
sta z80_h
                     ;- sbc hl, de  ; if remaining bytes < 4 we can continue
jcs __STRCONTINUE    ;- jr nc,__STRCONTINUE ; Otherwise, we realloc, to free some bytes

__STRREALLOC:
pla                  ;- pop hl
sta z80_h
pla
sta z80_l
jsr __REALLOC        ;- call __REALLOC	; Returns in HL a new pointer with BC bytes allocated
lda z80_l            ;- push hl
pha
lda z80_h
pha

__STRCONTINUE:	;   Pops hl and de SWAPPED
pla                  ;- pop de	;	DE = &a$
sta z80_d
pla
sta z80_e
pla                  ;- pop hl	; 	HL = &b$
sta z80_h
pla
sta z80_l
lda z80_d            ;- ld a,d		; Return if not enough memory for new length
sta z80_a
ora z80_e            ;- or e
bne *+3              ;- ret z		; Return if DE == NULL (0)
rts

__STRCPY:	; Copies string pointed by HL into string pointed by DE
; Returns DE as HL (new pointer)
lda z80_h                ;- ld a,h
sta z80_a
ora z80_l                ;- or l
jeq __NOTHING_TO_COPY    ;- jr z, __NOTHING_TO_COPY
                         ;- ld c,(hl)
inc z80_l                ;- inc hl
bne *+4
inc z80_h
ldy #$00                 ;- ld b,(hl)
lda (z80_hl),y
sta z80_b
                         ;- dec hl
inc z80_c                ;- inc bc
bne *+4
inc z80_b
inc z80_c                ;- inc bc
bne *+4
inc z80_b
lda z80_e                ;- push de
pha
lda z80_d
pha
                         ;- ldir
pla                      ;- pop hl
sta z80_h
pla
sta z80_l
rts                      ;- ret

__NOTHING_TO_COPY:
lda z80_e                ;- ex de,hl
ldx z80_l
stx z80_e
sta z80_l
lda z80_d
ldx z80_h
stx z80_d
sta z80_h
lda z80_e            ;- ld (hl),e
ldy #$00
sta (z80_hl),y
inc z80_l            ;- inc hl
bne *+4
inc z80_h
lda z80_d            ;- ld (hl),d
ldy #$00
sta (z80_hl),y
                     ;- dec hl
rts                  ;- ret
                     ;- ENDP

